#include <string.h>
#include <stdio.h>
#include <time.h>

#include "db_auth_mgmt.h"
#include "db_query.h"
#include "AGENCY.h"
#include "cJSON.h"

#define SERVER_VERSION "HttpServer/1.2"
#define MYSQL_SERVER	"172.24.0.247"
#define DBA_USERNAME	"dba"

/**
  * @brief  URI格式的json转换为标准json
  * @Notes  %22 -> "
  * @param  uri_json, Browser提交的json格式
  * @param  std_json, 转换后的标准json
  * @retval None.
  */
void uri_json_format(char* uri_json, int uri_json_len, char* std_json)
{
	int i,j; 
	for(i = 0, j = 0; i < uri_json_len;){
		if( uri_json[i] == '%' && uri_json[i+1] == '2' && uri_json[i+2] == '2'){
			std_json[j] = '"'; i += 3;
		}
		else{
			std_json[j] = uri_json[i]; i++;
		}
		j++;
	}
}

void URL_SCRIPT_BASENAME(char* SCRIPT_NAME, int SCRIPT_NAME_len, char* AGENCY)
{
	int i = SCRIPT_NAME_len-1;
	char buf[64]; int j = 0;
	while(SCRIPT_NAME[i] != '/'){ buf[j++] = SCRIPT_NAME[i]; i--; }
	for(i = 0; i < j; i++){	AGENCY[i] = buf[j-1-i]; }
}


/**
  * @brief  AGENCY处理函数
  * @Notes  通过判断代理标签实现不通的处理流程
  * @param  AGENCY, 处理标签 
  * @param  QUERY_STRING, Client提交的数据
  * @param  Session, Client 会话
  * @retval 0, 没有AGENCY处理
  * 		1, 有AGENCY处理
  */
int AGENCY_ACTION(char* AGENCY,
					SSL* ssl,
					char* QUERY_STRING,
					struct __client_session* Session)
{
	int flag=0;
	//printf("AGENCY > %s\n", AGENCY);
	/*
	 *	server端的代理标签(AGENCY.*)
	 *  AGENCY.ACCDB -> WebServer Agency: Access Database
	 *  AGENCY.xxx   -> WebServer Agency: *****
	 */
	if(strcmp(AGENCY, "AGENCY.ACCDB") == 0){
		struct __agency_fx_para fxpara;
		fxpara.ssl = ssl;
		fxpara.QUERY_STRING = QUERY_STRING;
		fxpara.Session = Session;
		agency_browser_access_db(&fxpara);
		flag = 1;
	}
	else if(strcmp(AGENCY, "AGENCY.xxx") == 0){	
		flag = 1; 
	}
	else{flag = 0;}
	return flag;
}

/**
  * @brief  Https-Server直接回复[字符串]到浏览器/客户端
  * @Notes  字符串快速响应, server端不需要文件读取操作
  * @param  ssl, OpenSSL句柄
  * @param  stream, 字符串数据
  * @retval None.
  */
void SendStream(SSL* ssl, char* stream )
{

	char buf[1460];
	int len = strlen(stream);
	//printf("len:%d, %s\n", len, stream);
	
	sprintf(buf, "HTTP/1.0 200 OK\r\n");
	SSL_write(ssl, buf, strlen(buf));
	sprintf( buf ,"Server: %s\r\n" , SERVER_VERSION );
	SSL_write(ssl, buf, strlen(buf));
	sprintf(buf, "Connection: close\r\n");
	SSL_write(ssl, buf, strlen(buf));
	sprintf(buf, "Content-Type: text/html\r\n");
	SSL_write(ssl, buf, strlen(buf));
	sprintf(buf, "\r\n");
	SSL_write(ssl, buf, strlen(buf));

	SSL_write(ssl, stream, len);
	sprintf(buf, "\r\n");
	SSL_write(ssl, buf, strlen(buf));
}

int AGENCY_DEBUG = 0;
void agency_browser_access_db(struct __agency_fx_para* FXPARA)
{
	SSL* ssl = FXPARA->ssl;
	char DATA_STRING[1024];
	uri_json_format(FXPARA->QUERY_STRING, strlen(FXPARA->QUERY_STRING), DATA_STRING);
	//printf("Browser submited variables: %s\n", FXPARA->QUERY_STRING);
	//printf("DATA_STRING: %s\n", DATA_STRING);
	cJSON *dat = cJSON_Parse(DATA_STRING);
	char* req = cJSON_GetObjectItem(dat, "req")->valuestring;
	char* user = cJSON_GetObjectItem(dat, "user")->valuestring;
	char* auth = cJSON_GetObjectItem(dat, "auth")->valuestring;
	time_t now; time(&now); char t_now[64]; strcpy(t_now, asctime(gmtime(&now))); t_now[strlen(t_now)-1]='\0'; //去掉最后一个字符'\n'
	MYSQL mysql_dba; MYSQL* dbsock_dba=NULL; mysql_init(&mysql_dba);
	//MYSQL mysql_usr; MYSQL* dbsock_usr=NULL; mysql_init(&mysql_usr);
	if(!(dbsock_dba = mysql_real_connect(&mysql_dba, MYSQL_SERVER, DBA_USERNAME, DBA_PASSWORD, "WPS", 3306, NULL, 0))){
		SendStream(ssl, "err#1.db.{dba conn failed}");	//dba connect failed.
		if(AGENCY_DEBUG) fprintf(stderr, "debug/> dba couldn't connect to db-server.\n");
		goto EndOfAgency;
	}else{
		if(AGENCY_DEBUG) fprintf(stderr, "debug/> dba connect to db-server success.\n" );
	}

	if(strcmp(req, "login") == 0)
	{
		USER_INFO ui;
		strcpy(ui.user, user); strcpy(ui.auth, auth);
		char sql[1024]; sprintf(sql, "SELECT auth FROM audit WHERE user='%s';", user);
		RET_ST retst_0, retst_1; 
		QUERY_VAR(sql, &retst_0, dbsock_dba);
 		if(AGENCY_DEBUG) fprintf(stderr, "debug/> auth string: %s\n", VARVAL(retst_0, 0, 0));
 		if(AGENCY_DEBUG) fprintf(stderr, "debug/> Client site IP %s:%d\n", FXPARA->Session->ip, FXPARA->Session->port);
 		if(retst_0.nRow > 0){
	    	/* 用户名存在, 判断密码是否符合 */
	    	if(strcmp(auth, VARVAL(retst_0, 0, 0)) == 0)
	    		sprintf(sql, "UPDATE audit SET tm_log='%s',ip_log='%s',st_log=1 WHERE user='%s';", t_now, FXPARA->Session->ip, user); 		
	    	else
	    		sprintf(sql, "UPDATE audit SET tm_log='%s',ip_log='%s',st_log=0 WHERE user='%s';", t_now, FXPARA->Session->ip, user);
	    	AUDIT_UPDATE(sql, dbsock_dba);

	    	sprintf(sql, "SELECT st_log FROM audit WHERE user='%s';", user);
			QUERY_VAR(sql, &retst_1, dbsock_dba);
			if(retst_1.nRow > 0){
				int st_log = atoi(VARVAL(retst_1, 0, 0));
		    	if(st_log == 1){
		    		SendStream(ssl, "ok.db.{user auth success}");		//login success.
		    	}else if(st_log == 0){
		    		SendStream(ssl, "err#2.db.{user auth failed}");	//password wrong.
		    	}
		    }
	    	QUERY_VAR_FREE(&retst_1);
		}else if(retst_0.nRow == 0){
			/* 用户名不存在 */
			SendStream(ssl, "err#3.db.{user invalid}");	//username invalid.
		}
    	QUERY_VAR_FREE(&retst_0);
	}
	else if(strcmp(req, "regist") == 0){
		USER_INFO ui; strcpy(ui.user, user); strcpy(ui.auth, auth); strcpy(ui.tm_reg, t_now);
		/* 1. mysql系统库添加新用户, 用于新用户连接数据库WPS
		 * 2. WPS库只开放一张表的读写权限给新用户, 表名称和用户名一致 
		 */
		int eno = MYSQL_ADD_USER(&ui, "WPS", user, dbsock_dba);
		if(eno == 1062){ 
			SendStream(ssl, "err#4.db.{user duplicate}"); 
			goto EndOfAgency;
		}
		/* 用户注册信息添加到审计表 */
		AUDIT_ADD_USER(&ui, "audit", dbsock_dba);
		SendStream(ssl, "ok.db.{user added}"); 
	}
	else if(strcmp(req, "CancelAccount") == 0){
		USER_INFO ui; strcpy(ui.user, user); strcpy(ui.auth, auth);
		MYSQL_DEL_USER(&ui, dbsock_dba);
		AUDIT_DEL_USER(&ui, "audit", dbsock_dba);
		SendStream(ssl, "ok.db.{account canceled}");
	}
	else if(strcmp(req, "datload") ==0){
		
	}
EndOfAgency:
	if(dbsock_dba){	mysql_close(&mysql_dba); dbsock_dba = NULL; }
	//if(dbsock_usr){	mysql_close(&mysql_usr); dbsock_usr = NULL; }
	
	cJSON_Delete(dat);
}